import java.applet.Applet;

import java.awt.*;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;
import java.util.ArrayList;
import java.util.LinkedList;

import engine.Kushali;
import engine.Matrix2X2;
import engine.PhysicsObject;
import engine.Vector;
import engine.Vertex;
import java.awt.event.*;

public class KushaliTest extends Applet implements Runnable, MouseListener {

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	static Image dbImage;
	private Graphics dbg;
	private boolean hasUpdated = false;
	
	int xpos;
	int ypos;
	Kushali k;
	ArrayList<PhysicsObject> objects;
	
	public void init(){

		this.setBackground(Color.black);
		this.resize(600,400);
		
		k = new Kushali();
		//k.createForce(new Vector(300,0), new Vector(0,1f), Float.POSITIVE_INFINITY);
		//k.enableLog(true);
		objects = new ArrayList<PhysicsObject>();
		
		for(int i = 0; i < 32; i++){
			PhysicsObject t = k.Triangle(new Vector(40 + (i % 4)* 40,
													40 + (i/4)*40),
													i == 0 ? 200 : 100,
													i == 0 ? 50 : 25,
													new Vector(-0.0f, -0.0f));
			objects.add(t);
		}
		
		objects.get(0).setVelocity(new Vector(1,0));
		
		//t2.setStatic(true);//setAngularVelo(0.05f);
		
		//buildFloor();
		//objects.add(t2);
		
		this.addMouseListener(this);

	}


	private void buildFloor(){
		for(int i = 0; i < 12; i++){
			PhysicsObject t2 = k.Square(new Vector(i*60 + 30, 370), 2, 60, new Vector(0.0f, 0.0f));
			t2.setStatic(true);
			
			objects.add(t2);
		}
	}
	
	@Override
	public void start() {
		// define a new thread
		Thread th = new Thread (this);
		// start this thread
		th.start(); 
	}
	
	@Override
	public void run() {
		// lower ThreadPriority
		Thread.currentThread().setPriority(Thread.MAX_PRIORITY);
		float currTime = 0;
		float lastTime = (float)System.nanoTime()/1000000f;
		//addMouseListener(this);
		lastTime --;
		// run a long while
		while (true)
		{
			
			currTime = (float)System.nanoTime()/1000000f;
			
			float dt = currTime - lastTime;
			
			objects.get(0).setAngularVelo(0.01f);
			
			k.update(dt);
			
			for(PhysicsObject o: objects){
				if(o.getPosition().getX() >= 600 || o.getPosition().getX() <= 0){
					o.setVelocity(Vector.mul(o.getVelocity(), new Vector(-1,0)));
				}
				
				if(o.getPosition().getY() >= 400 || o.getPosition().getY() <= 0)
					o.setVelocity(Vector.mul(o.getVelocity(), new Vector(0,-1)));
			}
			
			hasUpdated = true;
			//System.out.println(dt + "\n");
			// repaint the applet
			repaint();
			try
			{
				// Stop thread for 20 milliseconds
				Thread.sleep (16);		// initialize buffer
			}
			catch (InterruptedException ex)
			{
				// do nothing
			}
			
			lastTime = currTime;
		}
	}

	public void update(Graphics g){
		 //initialize buffer
		if (dbImage == null)
		{

			dbImage = createImage (this.getSize().width, this.getSize().height);
			dbg = dbImage.getGraphics ();

		}
		// clear screen in background
		dbg.setColor (getBackground ());
		dbg.fillRect (0, 0, this.getSize().width, this.getSize().height);

		// draw elements in background
		dbg.setColor (getForeground());
		paint (dbg);

		// draw image on the screen
		g.drawImage (dbImage, 0, 0, this); 
	}
	
	public void paint(Graphics g){
		g.setColor(Color.red);
		
		Vector last = null;
		Vector first = null;
		
			for(PhysicsObject o : objects){
				for(Vector p : /*o.temp_transform.size()>0 ? o.temp_transform :*/ transform(o)){
					if(last != null)
						g.drawLine((int)last.getX(), (int)last.getY(),
								   (int)p.getX(), (int)p.getY());
					if(first == null)
						first = p;
						
					last = p;
				}
				g.drawLine((int)last.getX(), (int)last.getY(),
						   (int)first.getX(), (int)first.getY());
				first = null;
				last = null;
				
				g.setColor(Color.white);
			}
		
			
		//g.drawLine(0, 0, xy.x, xy.y);
		
	}
	
	private ArrayList<Vector> transform(PhysicsObject o){
		ArrayList<Vector> transformed = new ArrayList<Vector>();
		
		Matrix2X2 transformer = new Matrix2X2(o.getAngle());
		transformer.setTranslation(o.getPosition());
		
		for(Vertex v : o.getVertexList()){
			transformed.add(transformer.applyTransform(v.getPos()));
		}
		
		return transformed;
	}
	
	/**
	 * @param args
	 */
	public static void main(String[] args) {

		Kushali k = new Kushali();
		
		k.update(0);
		System.out.println("Evaluated successfully");
	}


	@Override
	public void mouseClicked(MouseEvent e) {
		xpos = e.getX();
		ypos = e.getY();
		PhysicsObject po = objects.get(0);
		Vector pos = po.getPosition();
		float xDist = xpos - pos.getX();
		float yDist = ypos - pos.getY();
		//float angle = po.getAngularVelo();
		float rot = (float) Math.tan(yDist/xDist);
		po.setVelocity(new Vector(xDist/40f, yDist/40f));
		//po.setAngularVelo(angle + rot/10f);
		
		
	}


	@Override
	public void mousePressed(MouseEvent e) {
		// TODO Auto-generated method stub
		
	}


	@Override
	public void mouseReleased(MouseEvent e) {
		// TODO Auto-generated method stub
		
	}


	@Override
	public void mouseEntered(MouseEvent e) {
		// TODO Auto-generated method stub
		
	}


	@Override
	public void mouseExited(MouseEvent e) {
		// TODO Auto-generated method stub
		
	}
}
